import { useEffect, useRef, useState } from 'react'
import { TransformOffset } from './Transform'
import { Color } from './color'

type EventType = MouseEvent | React.MouseEvent<HTMLDivElement, MouseEvent>
type EventHandle = (e: EventType) => void
interface useColorDragProps {
  offset?: TransformOffset
  color: Color
  direction?: 'x' | 'y'
  containerRef: React.RefObject<HTMLDivElement | null>
  targetRef: React.RefObject<HTMLDivElement | null>
  onDragChange?: (offset: TransformOffset) => void
  calculate?: () => void
}

export function useColorDrag(
  props: useColorDragProps
): [TransformOffset, EventHandle] {
  const {
    color,
    offset,
    direction,
    containerRef,
    targetRef,
    calculate,
    onDragChange
  } = props
  const [offsetValue, setOffsetValue] = useState<TransformOffset>(
    offset || { x: 0, y: 0 }
  )
  const dragRef = useRef({
    flag: false
  })

  useEffect(() => {
    if (dragRef.current.flag === false) {
      const calcOffset = calculate?.()
      if (calcOffset) {
        setOffsetValue(calcOffset)
      }
    }
  }, [color])
  useEffect(() => {
    document.removeEventListener('mousemove', onDragMove)
    document.removeEventListener('mouseup', onDragEnd)
  }, [])
  const updateOffset: EventHandle = (e) => {
    const scrollXOffset =
      document.documentElement.scrollLeft || document.body.scrollLeft
    const scrollYOffset =
      document.documentElement.scrollTop || document.body.scrollTop

    const pageX = e.pageX - scrollXOffset
    const pageY = e.pageY - scrollYOffset

    const {
      x: rectX,
      y: rectY,
      width,
      height
    } = containerRef.current!.getBoundingClientRect()

    const { width: targetWidth, height: targetHeight } =
      targetRef.current!.getBoundingClientRect()

    const centerOffsetX = targetWidth / 2
    const centerOffsetY = targetHeight / 2

    const offsetX = Math.max(0, Math.min(pageX - rectX, width)) - centerOffsetX
    const offsetY = Math.max(0, Math.min(pageY - rectY, height)) - centerOffsetY

    const calcOffset = {
      x: offsetX,
      y: direction === 'x' ? offsetValue.y : offsetY
    }

    setOffsetValue(calcOffset)
    onDragChange?.(calcOffset)
  }
  const onDragMove: EventHandle = (e) => {
    e.preventDefault()
    updateOffset(e)
  }
  const onDragEnd: EventHandle = (e) => {
    document.removeEventListener('mousemove', onDragMove)
    document.removeEventListener('mouseup', onDragEnd)

    dragRef.current.flag = false
  }
  const onDragStart: EventHandle = (e) => {
    document.addEventListener('mousemove', onDragMove)
    document.addEventListener('mouseup', onDragEnd)
    dragRef.current.flag = true
  }
  return [offsetValue, onDragStart]
}
